﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CPPEI.Net.Original
{
    public class PackagePool
    {
        public byte[] Buffer { get; set; }
        private int _offset;
        private bool _isFirst = true;

        /// <summary>
        /// 已经收到的数据长度，每次append会添加，每次update会减少
        /// </summary>
        private int _dataLength;

        public PackagePool()
        {
            Buffer = new byte[10 * 1024 * 1024];
        }

        public Package GetNetBuffer()
        {
            int offset = 0;
            byte flag1 = BufferUtil.ByteFromBuffer(Buffer, ref offset);
            byte packageType = BufferUtil.ByteFromBuffer(Buffer, ref offset);
            byte command = BufferUtil.ByteFromBuffer(Buffer, ref offset);
            //byte replyMode = BufferUtil.ByteFromBuffer(Buffer, ref offset);
            //uint clientID = BufferUtil.UIntFromBuffer(Buffer, ref offset);
            ushort bufferLength = BufferUtil.UShortFromBuffer(Buffer, ref offset);
            byte flag2 = BufferUtil.ByteFromBuffer(Buffer, ref offset);

            if (flag1 == flag2
                && flag1 == 0x01
                && _dataLength >= bufferLength)
            {
                byte[] packageBuffer = new byte[bufferLength];
                System.Buffer.BlockCopy(Buffer, 0, packageBuffer, 0, bufferLength);

                Update(bufferLength);

                return new Package(packageBuffer);
            }
            else
            {
                // 出现了错误，这里不应该出现此情况
            }
            return null;
        }

        /// <summary>
        /// 更新buffer的内容，删除第一个包
        /// </summary>
        /// <param name="removeLength">从缓存区前部要删除的数据长度</param>
        private void Update(int removeLength)
        {
            for (int index = removeLength; index < _dataLength; index++)
            {
                Buffer[index - removeLength] = Buffer[removeLength];
            }
            _offset = 0;
            _dataLength -= removeLength;
        }

        public void AppendBuffer(byte[] buffer, int length)
        {
            if (_isFirst)
            {
                int offset = 0;
                byte flag1 = BufferUtil.ByteFromBuffer(buffer, ref offset);
                byte packageType = BufferUtil.ByteFromBuffer(Buffer, ref offset);
                byte command = BufferUtil.ByteFromBuffer(buffer, ref offset);
                //byte replyMode = BufferUtil.ByteFromBuffer(buffer, ref offset);
                //uint clientID = BufferUtil.UIntFromBuffer(buffer, ref offset);
                ushort bufferLength = BufferUtil.UShortFromBuffer(buffer, ref offset);
                byte flag2 = BufferUtil.ByteFromBuffer(buffer, ref offset);

                if (flag1 == flag2
                    && flag1 == 0x01)
                {
                    // 正确的包开始的头
                    System.Buffer.BlockCopy(buffer, 0, Buffer, _offset, length);
                    _offset += length;
                    _dataLength += length;
                    _isFirst = false;
                }
                else
                {
                    // 第一次必须加载一个正确的包头
                }
            }
            else
            {
                System.Buffer.BlockCopy(buffer, 0, Buffer, _offset, length);
                _offset += length;
                _dataLength += length;
            }
        }
    }

    public class Package
    {
        public const int HeaderLength = 6;

        /// <summary>
        /// 1byte
        /// 数据包的类型
        /// </summary>
        public byte PackageType { get; set; }

        /// <summary>
        /// 1byte
        /// </summary>
        public byte Command{get;set;}

        /// <summary>
        /// 2byte
        /// 包含头和数据信息的完整长度
        /// </summary>
        public ushort BufferLength { get; set; }

        private byte[] _buffer;

        public byte[] Buffer
        {
            get
            {
                return _buffer;
            }
        }

        public ushort DataLength { get; private set; }

        public bool IsFullPackage { get; private set; }

        /// <summary>
        /// 是否是有效的，true：有效，false：无效
        /// </summary>
        public bool IsValid { get; private set; }

        public Package(byte command, MemoryStream memoryStream)
            : this(0x02, command, memoryStream)
        {
        }

        internal Package(byte packageType, byte command, MemoryStream memoryStream)
        {
            this.DataLength = (ushort)memoryStream.Length;
            this.PackageType = packageType;
            this.Command = command;
            this.BufferLength = CalcBufferLength((ushort)memoryStream.Length);

            int offset = 0;
            _buffer = new byte[this.BufferLength];

            BufferUtil.ByteToBuffer(0x01, _buffer, ref offset);
            BufferUtil.ByteToBuffer(PackageType, _buffer, ref offset);
            BufferUtil.ByteToBuffer(Command, _buffer, ref offset);
            BufferUtil.UShortToBuffer(BufferLength, _buffer, ref offset);
            BufferUtil.ByteToBuffer(0x01, _buffer, ref offset);

            memoryStream.Seek(0, SeekOrigin.Begin);
            memoryStream.Read(_buffer, HeaderLength, (int)_buffer.Length);

            IsFullPackage = true;
            this.IsValid = true;
        }

        public Package(byte command, byte[] dataBuffer)
            : this(0x02, command, dataBuffer)
        {
        }

        public Package(byte packageType, byte command, byte[] dataBuffer)
        {
            this.DataLength = (ushort)dataBuffer.Length;
            this.PackageType = packageType;
            this.Command = command;
            this.BufferLength = CalcBufferLength((ushort)dataBuffer.Length);

            int offset = 0;
            _buffer = new byte[this.BufferLength];

            BufferUtil.ByteToBuffer(0x01, _buffer, ref offset);
            BufferUtil.ByteToBuffer(PackageType, _buffer, ref offset);
            BufferUtil.ByteToBuffer(Command, _buffer, ref offset);
            BufferUtil.UShortToBuffer(BufferLength, _buffer, ref offset);
            BufferUtil.ByteToBuffer(0x01, _buffer, ref offset);

            System.Buffer.BlockCopy(dataBuffer, 0, _buffer, HeaderLength, dataBuffer.Length);

            IsFullPackage = true;
            this.IsValid = true;
        }

        public Package(byte command, byte[] dataBuffer, int length)
            : this(0x02, command, dataBuffer, length)
        {
        }

        public Package(byte packageType, byte command, byte[] dataBuffer, int length)
        {
            this.DataLength = (ushort)dataBuffer.Length;
            this.PackageType = packageType;
            this.Command = command;
            this.BufferLength = CalcBufferLength((ushort)length);

            int offset = 0;
            _buffer = new byte[this.BufferLength];

            BufferUtil.ByteToBuffer(0x01, _buffer, ref offset);
            BufferUtil.ByteToBuffer(PackageType, _buffer, ref offset);
            BufferUtil.ByteToBuffer(Command, _buffer, ref offset);
            BufferUtil.UShortToBuffer(BufferLength, _buffer, ref offset);
            BufferUtil.ByteToBuffer(0x01, _buffer, ref offset);

            System.Buffer.BlockCopy(dataBuffer, 0, _buffer, HeaderLength, length);

            IsFullPackage = true;
            this.IsValid = true;
        }

        /// <summary>
        /// 从buffer里获取一个netbuffer数据
        /// </summary>
        /// <param name="buffer"></param>
        public Package(byte[] buffer)
        {
            int offset = 0;
            byte flag1 = BufferUtil.ByteFromBuffer(buffer, ref offset);
            byte packageType = BufferUtil.ByteFromBuffer(buffer, ref offset);
            byte command = BufferUtil.ByteFromBuffer(buffer, ref offset);
            ushort bufferLength = BufferUtil.UShortFromBuffer(buffer, ref offset);
            byte flag2 = BufferUtil.ByteFromBuffer(buffer, ref offset);

            if (flag1 == flag2
                && flag1 == 0x01)
            {
                this.PackageType = packageType;
                this.Command = command;
                this.BufferLength = bufferLength;
                this.DataLength = (ushort)(this.BufferLength - HeaderLength);
                this._buffer = buffer;

                this.IsValid = true;
                this.IsFullPackage = true;
            }
            else
            {
                throw new Exception("数据内容不是一个数据包的格式");
            }
        }

        /// <summary>
        /// 计算数据的总长度
        /// </summary>
        /// <param name="dataLength"></param>
        /// <returns></returns>
        public static ushort CalcBufferLength(ushort dataLength)
        {
            return (ushort)(dataLength + HeaderLength);
        }

        /// <summary>
        /// 构建一个系统内部的数据包
        /// </summary>
        /// <param name="command"></param>
        /// <param name="dataBuffer"></param>
        /// <returns></returns>
        internal static Package BuildSysPackage(byte command, byte[] dataBuffer)
        {
            Package package = new Package(0x01, command, dataBuffer);
            return package;
        }
    }
}
